﻿/* Copyright 2011 Michiel Fortuin
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * */

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Text;

namespace sharplog
{
	/// <summary>
	/// Implements the Syslog protocol (RFC 5424).
	/// </summary>
	public class Syslog : Formater
	{
		private const string NILVALUE = "-";
		/// <summary>
		/// the protocol version
		/// </summary>
		public const int VERSION = 1;

		/// <summary>
		/// Application name that must be send with the messages
		/// </summary>
		public string AppName { get; set; }
		/// <summary>
		/// The process id that must be send with the messages. if this is not set, null or empty it wil use the PID.
		/// </summary>
		public string ProcID { get; set; }

		public Syslog()
		{
		}

		public Syslog(string appname, string ProcId = null)
		{
			this.AppName = appname;
			this.ProcID = ProcId;
		}

		/// <summary>
		/// Constructs a message for sending
		/// </summary>
		/// <param name="level">The level of the message.</param>
		/// <param name="facility">The facility from where the log message originates.</param>
		/// <param name="messageID">An Id given to the message.</param>
		/// <param name="message">The message itself.</param>
		/// <returns>An object for a specifice sender.</returns>
		internal override object ConstructMessage(Level level, Facility facility, string messageID, string message = "")
		{
			int prival = ((int)facility) * 8 + ((int)level);
			string pri = string.Format("<{0}>", prival);
			string timestamp =
				new DateTimeOffset(DateTime.Now, TimeZoneInfo.Local.GetUtcOffset(DateTime.Now)).ToString("yyyy-MM-ddTHH:mm:ss.ffffffzzz");
			string hostname = Dns.GetHostEntry(Environment.UserDomainName).HostName;
			string appName = string.IsNullOrWhiteSpace(this.AppName) ? NILVALUE : this.AppName;
			string procId = string.IsNullOrWhiteSpace(this.ProcID) ? Process.GetCurrentProcess().Id.ToString() : this.ProcID;
			string msgId = string.IsNullOrWhiteSpace(messageID) ? NILVALUE : messageID;

			string header = string.Format("{0}{1} {2} {3} {4} {5} {6}", pri, VERSION, timestamp, hostname, appName, procId, msgId);
			string SD = NILVALUE;

			List<byte> syslogMsg = new List<byte>();
			syslogMsg.AddRange(System.Text.Encoding.ASCII.GetBytes(header));
			syslogMsg.AddRange(System.Text.Encoding.ASCII.GetBytes(" "));
			syslogMsg.AddRange(System.Text.Encoding.ASCII.GetBytes(SD));
			if (message != "")
			{
				syslogMsg.AddRange(System.Text.Encoding.ASCII.GetBytes(" BOM"));
				syslogMsg.AddRange(System.Text.Encoding.UTF8.GetBytes(message));
			}

			return syslogMsg.ToArray();
		}
	}
}
